package com.sunxd.zstudy.mybatise.domain.service.engine.dispatcher.interactive;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.sunxd.zstudy.mybatise.domain.annotation.LimitHandler;
import com.sunxd.zstudy.mybatise.domain.dto.LimitCondition;
import com.sunxd.zstudy.mybatise.domain.service.engine.handler.limit.AbstractLimitHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * Description:
 */
@Component
@Slf4j
public class InteractiveLimitHandlerDispatcher implements ApplicationContextAware {

    private Map<String, AbstractLimitHandler> map = Maps.newHashMap();;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        Map<String, Object> beansWithAnnotation = applicationContext.getBeansWithAnnotation(LimitHandler.class);
//        beansWithAnnotation.values().stream().sorted(Comparator.comparing()) todo sort
        Map<String, List<AbstractLimitHandler>> mapList = Maps.newHashMap();
        for (Object bean : beansWithAnnotation.values()) {
            if (bean instanceof AbstractLimitHandler) {
                LimitHandler limitHandler = bean.getClass().getAnnotation(LimitHandler.class);
                if (mapList.containsKey(limitHandler.group())) {
                    mapList.get(limitHandler.group()).add((AbstractLimitHandler) bean);
                } else {
                    mapList.put(limitHandler.group(), Lists.newArrayList((AbstractLimitHandler) bean));
                }
            }
        }
        for (Map.Entry<String, List<AbstractLimitHandler>> next : mapList.entrySet()) {
            List<AbstractLimitHandler> limitHandlers = next.getValue();
            int size = limitHandlers.size();
            for (int i = 0; i < size; i++) {
                if (i == size - 1) {
                    limitHandlers.get(i).setNextHandler(null);
                } else {
                    limitHandlers.get(i).setNextHandler(limitHandlers.get(i + 1));
                }
            }
            map.put(next.getKey(), limitHandlers.get(0));
        }

    }

    public void doExecute(String group,Map<String, LimitCondition> limit){
        if(map.containsKey(group)){
            map.get(group).execute(limit);
        }
    }
}
